import sys
print('sys.path', sys.path)

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
import django
django.setup()

from datetime import datetime
import threading
import paho.mqtt.client as mqtt
from threading import Thread
import logging
import pymssql
from iot.models import Gradation, Cabinet, Point, Unit
from common.tdengine import load_tdengine_pool
import json

_logger = logging.getLogger(__file__)

# host = '192.168.0.244'
host = '39.98.122.153'
TEMP_TYPE1 = 'T'
TEMP_TYPE2 = 'H'
publish_topic = 'iot/air/trans'

pg_lock = threading.Lock()
#1表示报警（超过阈值也属于报警），0表示没有报警

# 其目的是处理传感器数据，并根据特定的条件发布警告信息。
def trans(client, data_list1):
    # 创建一个字符串 key，它由位置、设备和传感器名称连接而成，通常用于唯一标识一个传感器。
    table1 = data_list1[-1]
    parts = table1.split('_')
    key = parts[1]+'.'+parts[2]+'.'+parts[0]
    value_now = float(data_list1[-3])
    # 创建一个字典 payload，其键为之前生成的 key，值为处理后的 value_now
    payload = {key: value_now}
    # 发布(不管是否报警)
    client.publish(publish_topic, json.dumps(payload, ensure_ascii=False))
    # 创建点位表对象
    points = Point.objects.filter(code=table1)
    # 并不是外键就是单独的字段
    warm_warning = points.first().cabinet.warm_warning
    warm_early_warning = points.first().cabinet.warm_early_warning
    if warm_warning:
        # 如果传感器传过来的值大于报警值
        if value_now > warm_warning:
            # 发布传感器信息(报警)
            client.publish(publish_topic, json.dumps({key+'_warn': 1}, ensure_ascii=False))
            return
    if warm_early_warning:
        # 如果传感器的值大于预警值
        if value_now > warm_early_warning:
            # # 发布传感器信息
            client.publish(publish_topic, json.dumps({key+'_warn': 1}, ensure_ascii=False))
            return
    client.publish(publish_topic, json.dumps({key+'_warn': 0}, ensure_ascii=False))

class Sub(Thread):

    def __init__(self, topic, username, password, host, port, client_id):
        super().__init__()
        self.topic = topic
        self.client = mqtt.Client(client_id)
        self.client.username_pw_set(username, password)
        self.client.connect(host=host, port=port)
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message
        self.state = True
        self.lt = None

    def on_connect(self, client, userdata, flags, rc):
        rc = str(rc)
        if rc == '0':
            self.client.subscribe(self.topic)
            print("链接成功")
        else:
            _logger.info(f'连接失败: 状态码为{rc}')

    def on_message(self, client, userdata, msg):
        try:
            data_list = eval(msg.payload.decode('utf-8'))
            if data_list:
                # 对源数据保留两位小数处理
                values_list = [format(float(value), '.2f') for value in data_list.values()]
                # 添加时间
                time = datetime.now()
                values_list.append(time)
                t = threading.Thread(target=Sub.write_to_td, args=(self, values_list,))
                t.start()
        except Exception as e:
            _logger.error(f'e: {e}')

    def write_to_td(self, data_list):

        time = data_list[-1]
        data_list.pop()  # 删除列表的最后一个元素
        for index, value in enumerate(data_list):
            # print(f"索引: {index}, 值: {value}")
            type = "T" if (index + 2) % 2 == 0 else "H"
            if index < 2:
                point = "control1"
            elif index < 4:
                point = "north"
            else:
                point = "south"
            # taos的子表名称以及标签的名称
            table = type+"_lunzhen_"+point
            # 制作pg表的值
            data_list1 = []
            data_list1.append(value);
            data_list1.append(time);
            data_list1.append(table);
            # 插入pg
            Sub.write_to_pg(data_list1)
            # 报警上传
            if type == TEMP_TYPE1 or type == TEMP_TYPE2:
                trans(self.client, data_list1)
            # 向taos中插入子表
            with load_tdengine_pool().get() as cursor:
                super_table = "iot1"
                sql = f"INSERT INTO {table} USING {super_table} TAGS ('{table}') VALUES ('{time}', '{value}');"
                print(sql)
                cursor.execute(sql)



    @staticmethod
    def write_to_pg(data_list):
        with pg_lock:
            value = data_list[-3]
            time = data_list[-2]
            # 对传过来的数据进行处理
            table1 = data_list[-1]
            parts = table1.split('_')
            # mqtt传过来电表编号,分层编码
            if(parts[0]=='T'):
                type  = 'temputer'
            else:
                type = 'hygrometer'

            cabinet = Cabinet.objects.filter(code=parts[2])   # 电柜必须有匹配的（具体看mqtt）
            if cabinet.count() == 0:
                _logger.info('请配置相关配电站')
                return
            gradation = Gradation.objects.filter(code=type)  # 分层必须有匹配的（具体看MQTT发什么）
            if gradation.count() == 0:
                _logger.info('请配置相关电压、温度层级属性')
                return
            unit = Unit.objects.filter(type=parts[0])   # 类型必有匹配的一般是T
            if unit.count() == 0:
                _logger.info('请配置相关单位类型')
                return

            points = Point.objects.filter(code=table1)   # 点位表中必须有
            if points.count() == 0:
                # pass
                Point.objects.create(gradation=gradation.first(), unit=unit.first(),
                                     cabinet=cabinet.first(), **{'code': table1, 'value': value,
                                                                 'name': cabinet.first().name+gradation.first().name,
                                                                 'dept_belong_id': cabinet.first().dept_belong_id})
            else:
                value = float(value)
                Point.update(table1, **{'value': value, 'update_datetime': time})







    def run(self):
        self.client.loop_forever()

if __name__ == '__main__':
    Sub(topic='hanji/lunzhen-humiture', username='emqx', password='public', host='39.98.122.153', port=1883, client_id='dasuidasdasdsdaj').start()

